/**
  ******************************************************************************
  * @file    mdr32f8_spw.h
  * @author  Milandr Application Team
  * @version V1.0.0
  * @date    18/08/2022
  * @brief   This file contains the defines and typedef and functions prototypes.
  *
  ******************************************************************************
  * <br><br>
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, MILANDR SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
  * OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2024 Milandr</center></h2>
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPACEWIRE_H
#define __SPACEWIRE_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "MDR1986VE8T.h"
#include "mdr32f8_config.h"

/** @addtogroup __MDR32F8_StdPeriph_Driver MDR32F8 Standard Peripherial Driver
  * @{
  */

/** @addtogroup SPW SPW
  * @{
  */

/** @defgroup SPW_Clock_BRG
  * @{
  */

#define IS_SPW_CLOCK_BRG(BRG)              ((BRG) <= 127)

#define SPW_DIV_Msk                        ((uint32_t)0x0000FFFF)
#define SPW_CLK_EN                         (1<<16)
#define SPW_CLKSRC_msk                     ((uint32_t)0xF0000000) 
#define SPW_CLKSRC_offs                    28

#define SPW_CLKdiv1                        ((uint32_t)0x00000000)
#define SPW_CLKdiv2                        ((uint32_t)0x00000001)
#define SPW_CLKdiv4                        ((uint32_t)0x00000003)
#define SPW_CLKdiv8                        ((uint32_t)0x00000007)
#define SPW_CLKdiv16                       ((uint32_t)0x0000000F)
#define SPW_CLKdiv32                       ((uint32_t)0x0000001F)
#define SPW_CLKdiv64                       ((uint32_t)0x0000003F)
#define SPW_CLKdiv128                      ((uint32_t)0x0000007F)

/** @} */ /* End of group CAN_Clock_BRG */

/** @defgroup SPW_DMA_request SPW DMA request
  * @{
  */

#define SPW_DMATXEN                         ((uint32_t)0x00000080)
#define SPW_DMARXEN                         ((uint32_t)0x00000100)

#define IS_SPW_DMAREQ(DMAREQ)               ((((DMAREQ) == SPW_DMATXEN) || \
                                             ((DMAREQ) == SPW_DMARXEN)) || \
                                             ((DMAREQ) == (SPW_DMATXEN | SPW_DMARXEN)))

/** @} */ /* End of group SSP_DMA_request */

/** @defgroup SPW_Interrupt_definition SPW Interrupt definition
  * @{
  */

#define SPW_IT_INTENTIME                   ((uint32_t)0x00000010)
#define SPW_IT_INTENERR                    ((uint32_t)0x00000020)
#define SPW_IT_INTENLINK                   ((uint32_t)0x00000040)
#define SPW_IT_INTENRXNE                   ((uint32_t)0x00000200)
#define SPW_IT_INTERXF                     ((uint32_t)0x00000400)
#define SPW_IT_INTETXE                     ((uint32_t)0x00000800)
#define SPW_IT_INTETXF                     ((uint32_t)0x00001000)
#define SPW_IT_INTENRXDES                  ((uint32_t)0x00002000)
#define SPW_IT_INTENTXDES                  ((uint32_t)0x00004000)
#define SPW_IT_INTERXF34                   ((uint32_t)0x00008000)

#define SPW_IT_MASK             (SPW_IT_INTENTIME | \
                                 SPW_IT_INTENERR  | \
                                 SPW_IT_INTENLINK | \
                                 SPW_IT_INTENRXNE | \
                                 SPW_IT_INTERXF   | \
                                 SPW_IT_INTETXE   | \
                                 SPW_IT_INTETXF   | \
                                 SPW_IT_INTENRXDES | \
                                 SPW_IT_INTENTXDES | \
                                 SPW_IT_INTERXF34)
                                 
                                 
#define IS_SPW_ITS(IT)  (((IT) & (~SPW_IT_MASK)) == 0)                                 

#define IS_SPW_CONFIG_IT(IT)               (((IT) == SPW_IT_INTENTIME)  || ((IT) == SPW_IT_INTENERR)  || \
                                             ((IT) == SPW_IT_INTENLINK)  || ((IT) == SPW_IT_INTENRXNE)  || \
                                             ((IT) == SPW_IT_INTERXF)  || ((IT) == SPW_IT_INTETXE)  || \
                                             ((IT) == SPW_IT_INTETXF)  || ((IT) == SPW_IT_INTENRXDES) || \
                                             ((IT) == SPW_IT_INTENTXDES) || ((IT) == SPW_IT_INTERXF34)

/** @} */ /* End of group SPW_Interrupt_definition */

/**
  * @brief SPW PHY TST[2:0] type
  */ 
typedef enum
{
    SPW_TST_VALUE_DEFAULT    = ((uint32_t)0x00),
    SPW_TST_VALUE_1          = ((uint32_t)0x01),
    SPW_TST_VALUE_2          = ((uint32_t)0x02),
    SPW_TST_VALUE_3          = ((uint32_t)0x03),
    SPW_TST_VALUE_4          = ((uint32_t)0x04),
    SPW_TST_VALUE_5          = ((uint32_t)0x05),
    SPW_TST_VALUE_6          = ((uint32_t)0x06),
    SPW_TST_VALUE_7          = ((uint32_t)0x07)
    
} SPW_Phy_Test_Value;

#define IS_SPW_PHY_TST_VALUE(VALUE) (((VALUE) == SPW_TST_VALUE_DEFAULT) || ((VALUE) == SPW_TST_VALUE_1) || \
                                     ((VALUE) == SPW_TST_VALUE_2) || ((VALUE) == SPW_TST_VALUE_3) || \
                                     ((VALUE) == SPW_TST_VALUE_4) || ((VALUE) == SPW_TST_VALUE_5) || \
                                     ((VALUE) == SPW_TST_VALUE_6) || ((VALUE) == SPW_TST_VALUE_7))
/**
  * @brief SPW PHY TRIM[2:0] voltage reference digital trim
  */ 
typedef enum
{
    SPW_TRIM_VALUE_1_25      = ((uint32_t)0x00),
    SPW_TRIM_VALUE_1_23      = ((uint32_t)0x01),
    SPW_TRIM_VALUE_1_22      = ((uint32_t)0x02),
    SPW_TRIM_VALUE_1_21      = ((uint32_t)0x03),
    SPW_TRIM_VALUE_1_2       = ((uint32_t)0x04),
    SPW_TRIM_VALUE_1_18      = ((uint32_t)0x05),
    SPW_TRIM_VALUE_1_16      = ((uint32_t)0x06),
    SPW_TRIM_VALUE_1_15      = ((uint32_t)0x07)
    
} SPW_Phy_Trim_Value;

#define IS_SPW_PHY_TRIM_VALUE(TRIM)     (((TRIM) == SPW_TRIM_VALUE_1_25) || ((TRIM) == SPW_TRIM_VALUE_1_23) || \
                                        ((TRIM) == SPW_TRIM_VALUE_1_22) || ((TRIM) == SPW_TRIM_VALUE_1_21) || \
                                        ((TRIM) == SPW_TRIM_VALUE_1_2) || ((TRIM) == SPW_TRIM_VALUE_1_18) || \
                                        ((TRIM) == SPW_TRIM_VALUE_1_16) || ((TRIM) == SPW_TRIM_VALUE_1_15))
/**                                  
  * @brief SPW broadcast packet type
  */  
  
typedef enum
{
    SPW_TIME_CODE       = ((uint32_t)0x00),
    SPW_INVALID_CODE    = ((uint32_t)0x01),
    SPW_INTERRUPT_CODE  = ((uint32_t)0x02),
    SPW_FORBIDDEN_CODE  = ((uint32_t)0x03)

} SPW_Broadcast_Type_Packet;

#define IS_SPW_BROADCAST_TYPE(TYPE)     (((TYPE) == SPW_TIME_CODE) || ((TYPE) == SPW_INVALID_CODE) || \
                                        ((TYPE) == SPW_INTERRUPT_CODE) || ((TYPE) == SPW_FORBIDDEN_CODE))

/**
  * @brief SPW Descriptor Number
  */
typedef enum
{
    SPW_DESC_0        = ((uint32_t)0x00), /*!< Specifies the SPW Descriptor Number 0.  */
    SPW_DESC_1        = ((uint32_t)0x01), /*!< Specifies the SPW Descriptor Number 1.  */
    SPW_DESC_2        = ((uint32_t)0x02), /*!< Specifies the SPW Descriptor Number 2.  */
    SPW_DESC_3        = ((uint32_t)0x03), /*!< Specifies the SPW Descriptor Number 3.  */
    SPW_DESC_4        = ((uint32_t)0x04), /*!< Specifies the SPW Descriptor Number 4.  */
    SPW_DESC_5        = ((uint32_t)0x05), /*!< Specifies the SPW Descriptor Number 5.  */
    SPW_DESC_6        = ((uint32_t)0x06), /*!< Specifies the SPW Descriptor Number 6.  */
    SPW_DESC_7        = ((uint32_t)0x07), /*!< Specifies the SPW Descriptor Number 7.  */
    SPW_DESC_8        = ((uint32_t)0x08), /*!< Specifies the SPW Descriptor Number 8.  */
    SPW_DESC_9        = ((uint32_t)0x09), /*!< Specifies the SPW Descriptor Number 9.  */
    SPW_DESC_10       = ((uint32_t)0x0A), /*!< Specifies the SPW Descriptor Number 10. */
    SPW_DESC_11       = ((uint32_t)0x0B), /*!< Specifies the SPW Descriptor Number 11. */
    SPW_DESC_12       = ((uint32_t)0x0C), /*!< Specifies the SPW Descriptor Number 12. */
    SPW_DESC_13       = ((uint32_t)0x0D), /*!< Specifies the SPW Descriptor Number 13. */
    SPW_DESC_14       = ((uint32_t)0x0E), /*!< Specifies the SPW Descriptor Number 14. */
    SPW_DESC_15       = ((uint32_t)0x0F), /*!< Specifies the SPW Descriptor Number 15. */
    SPW_DESC_ALL      = ((uint32_t)0x10), /*!< Specifies the SPW All Descriptors. */
 
} SPW_Descriptor_Number;

#define IS_SPW_DESC_NUM(NUM) (((NUM) == SPW_DESC_0 ) || \
                             ((NUM) == SPW_DESC_1 ) || \
                             ((NUM) == SPW_DESC_2 ) || \
                             ((NUM) == SPW_DESC_3 ) || \
                             ((NUM) == SPW_DESC_4 ) || \
                             ((NUM) == SPW_DESC_5 ) || \
                             ((NUM) == SPW_DESC_6 ) || \
                             ((NUM) == SPW_DESC_7 ) || \
                             ((NUM) == SPW_DESC_8 ) || \
                             ((NUM) == SPW_DESC_9 ) || \
                             ((NUM) == SPW_DESC_10) || \
                             ((NUM) == SPW_DESC_11) || \
                             ((NUM) == SPW_DESC_12) || \
                             ((NUM) == SPW_DESC_13) || \
                             ((NUM) == SPW_DESC_14) || \
                             ((NUM) == SPW_DESC_15) || \
                             ((NUM) == SPW_DESC_ALL))


/* Bit field masks: */
#define SPW_STATUS_STATE_Msk    ((uint32_t)0x00000007)
#define SPW_DESC_LENGHT_Msk     ((uint32_t)0x01FFFFFF)
#define SPW_DESC_TYPE_Msk       ((uint32_t)0x60000000)
#define SPW_DESC_RDY            ((uint32_t)0x80000000)

/**
  * @brief SPW Ends of packet
  */
typedef enum
{
    SPW_EOP = ((uint32_t) 0x20000000),
    SPW_EEP = ((uint32_t) 0x40000000)
    
} SPW_Type_Packet;

#define IS_SPW_TYPE_PACKET(TYPE_PACKET)     ((((TYPE_PACKET) == SPW_EOP) || \
                                             ((TYPE_PACKET) == SPW_EEP)))

/**
  * @brief SPW SPW Flags
  */
typedef enum
{
    SPW_FLAG_PERR       = ((uint32_t)0x0008),
    SPW_FLAG_DSCERR     = ((uint32_t)0x0010),
    SPW_FLAG_ESCERR     = ((uint32_t)0x0020),
    SPW_FLAG_CREDERR    = ((uint32_t)0x0040),
    SPW_FLAG_GOTTIME    = ((uint32_t)0x0080),
    SPW_FLAG_RXNE       = ((uint32_t)0x0100),
    SPW_FLAG_RXF        = ((uint32_t)0x0200),
    SPW_FLAG_TXE        = ((uint32_t)0x0400),
    SPW_FLAG_TXF        = ((uint32_t)0x0800),
    SPW_FLAG_RXDESC     = ((uint32_t)0x1000),
    SPW_FLAG_TXDESC     = ((uint32_t)0x2000),
    SPW_FLAG_RXF34      = ((uint32_t)0x4000)
    
} SPW_Flags_TypeDef;

#define IS_SPW_FLAG(FLAG)  (((FLAG) == SPW_FLAG_PERR  ) || ((FLAG) == SPW_FLAG_DSCERR)   || \
                             ((FLAG) == SPW_FLAG_ESCERR) || ((FLAG) == SPW_FLAG_CREDERR) || \
                             ((FLAG) == SPW_FLAG_GOTTIME) || ((FLAG) == SPW_FLAG_RXNE)   || \
                             ((FLAG) == SPW_FLAG_RXF ) || ((FLAG) == SPW_FLAG_TXE )      || \
                             ((FLAG) == SPW_FLAG_TXF ) || ((FLAG) == SPW_FLAG_RXDESC )   || \
                             ((FLAG) == SPW_FLAG_TXDESC ||((FLAG) == SPW_FLAG_RXF34 ) ))

#define SPW_STATUS_Msk  (SPW_FLAG_PERR    | \
                         SPW_FLAG_DSCERR  | \
                         SPW_FLAG_ESCERR  | \
                         SPW_FLAG_CREDERR | \
                         SPW_FLAG_GOTTIME | \
                         SPW_FLAG_RXDESC  |  \
                         SPW_FLAG_RXDESC )

#define IS_SPW_STATUS(STATUS)    (((STATUS) & SPW_STATUS_Msk) == (STATUS))

/**
  * @brief SPW States of link interface
  */
typedef enum
{
    SPW_State_ErrorReset  = ((uint32_t)0x00),
    SPW_State_ErrorWait   = ((uint32_t)0x01),
    SPW_State_Ready       = ((uint32_t)0x02),
    SPW_State_Started     = ((uint32_t)0x03),
    SPW_State_Connecting  = ((uint32_t)0x04),
    SPW_State_Run         = ((uint32_t)0x05)
    
} SPW_States_TypeDef;


/**
  * @brief SpaceWire Init Structure definition
  * @note  The user should not configure all the SPW_States_TypeDef structure's fields.
  *        By calling the SPW_StructInit function the structure’s fields are set to their default values.
  *        Only the parameters that will be set to a non-default value should be configured.
  */
typedef struct
{
    FunctionalState            SPW_Link_Error_Reset;                 /*!< The state of the Error_Reset Link interface.
                                                                     This parameter can be a value of @ref FunctionalState. */
    FunctionalState            SPW_Link_Ready_Started;               /*!< The state of the Ready_Started transfer Link interface.
                                                                     This parameter can be a value of @ref FunctionalState. */
    FunctionalState            SPW_Link_Autostart;                   /*!< The state of the Autostart transfer Link interface.
                                                                     This parameter can be a value of @ref FunctionalState. */ 
    uint8_t                    SPW_DIVCNT;                           /*!< This member configures the SPW clock divider.
                                                                     This parameter is an even number from 1 to 255. */
    uint8_t                    SPW_DIVCNTDEF;                        /*!< This member configures the SPW clock divider.
                                                                     This parameter is an even number from 1 to 255. */ 
    uint8_t                    SPW_Pause_Dsctime;                    /*!< The number of cycles of the processor core frequency required for the counter operation interval is 850 ns.
                                                                     This parameter is an even number from 0 to 255. */ 
    uint16_t                   SPW_Pause_Restime;                    /*!< The number of cycles of the processor core frequency required for the counter operation interval is 6.4 us.
                                                                     This parameter is an even number from 0 to 2047. */  
    FunctionalState            SPW_PHY_Ir_Down;                         /*!< Current reduction by 12.5%.
                                                                     This parameter can be a value of @ref FunctionalState. */
    FunctionalState            SPW_PHY_Ir_Up;                            /*!< Current increase by 12.5%.
                                                                     This parameter can be a value of @ref FunctionalState. */
    FunctionalState            SPW_PHY_Out_En;                          /*!< Enable the transceiver.
                                                                     This parameter can be a value of @ref FunctionalState. */
    FunctionalState            SPW_PHY_SELR;                            /*!< Use an external stable resistor on the SPW_EXTR pin.
                                                                     This parameter can be a value of @ref FunctionalState. */
    SPW_Phy_Trim_Value         SPW_PHY_TRIM;                            /*!< Value of voltage reference digital trim.
                                                                     This parameter can be a value of @ref SPW_Phy_Trim_Value.*/
    FunctionalState            SPW_PHY_EN_BNG;                           /*!< Enable REF of SPW.
                                                                     This parameter can be a value of @ref FunctionalState.*/
    uint8_t                    SPW_PHY_TRIMR;                            /*!< Trim value of the internal current reference resistor.
                                                                     This parameter is an even number from 0 to 255. */                                                               
    SPW_Phy_Test_Value         SPW_PHY_TST;                              /*!< Value of the test phy mode.
                                                                     This parameter can be a value of @ref SPW_Phy_Test_Value.*/                                                    
    
} SPW_InitTypeDef;  


/** @defgroup SPW_Exported_Functions SPW Exported Functions
  * @{
  */

void SPW_DeInit(MDR_SPW_TypeDef* SPWx);
void SPW_StructInit(SPW_InitTypeDef * SPW_InitStruct);
void SPW_Init(MDR_SPW_TypeDef* SPWx, const SPW_InitTypeDef* SPW_InitStruct);
void SPW_CLK_en(uint32_t SPW_CLK_DIV);

void SPW_Cmd(MDR_SPW_TypeDef* SPWx, FunctionalState NewState);
void SPW_PHYCmd(MDR_SPW_TypeDef* SPWx, FunctionalState NewState);

FlagStatus SPW_GetFlagStatus(MDR_SPW_TypeDef * SPWx, SPW_Flags_TypeDef SPW_Flag);
void SPW_ClearFlag(MDR_SPW_TypeDef* SPWx, uint32_t Flags);
SPW_States_TypeDef SPW_GetLinkState (MDR_SPW_TypeDef * SPWx);

void SPW_ITConfig (MDR_SPW_TypeDef* SPWx, uint32_t SPW_IT, FunctionalState NewState);
void SPW_DMACmd(MDR_SPW_TypeDef* SPWx, uint32_t SPW_DMAReq, FunctionalState NewState);

void SPW_InitTransmitDesc(MDR_SPW_TypeDef* SPWx, SPW_Type_Packet Type_packet, uint32_t length);
uint32_t SPW_ReceiveData(MDR_SPW_TypeDef* SPWx);
void SPW_SendData(MDR_SPW_TypeDef* SPWx, uint32_t Data);
void SPW_SendPacket(MDR_SPW_TypeDef* SPWx, SPW_Type_Packet Type_packet, uint32_t *data, uint32_t length);

void SPW_ClearRXDesc (MDR_SPW_TypeDef* SPWx, uint32_t Num);
void SPW_ClearTXDesc (MDR_SPW_TypeDef* SPWx, uint32_t Num);

SPW_Type_Packet SPW_GetRXDescPacketType (MDR_SPW_TypeDef* SPWx, uint32_t Num);
uint32_t SPW_GetRXDescPacketLength (MDR_SPW_TypeDef* SPWx, uint32_t Num);

FunctionalState SPW_IsRXDescReady (MDR_SPW_TypeDef* SPWx, uint32_t Num);

void SPW_SetTimeTXMarker(MDR_SPW_TypeDef* SPWx, SPW_Broadcast_Type_Packet Type, uint32_t Time);
SPW_Broadcast_Type_Packet SPW_GetTimeRXMarker(MDR_SPW_TypeDef* SPWx, uint32_t* Time);
void SPW_StartTransmissionTimeTXMarker(MDR_SPW_TypeDef* SPWx);

void SPW_InitRxDMA(MDR_SPW_TypeDef* SPWx, uint32_t *receive_buffer, uint32_t size, uint8_t dmaRealCh, FunctionalState useDMAIT);

/** @} */ /* End of group SPW_Exported_Functions */

/** @} */ /* End of group SPW */

/** @} */ /* End of group __MDR32F8_StdPeriph_Driver */

#ifdef __cplusplus
} // extern "C" block end
#endif

#endif /* __SPACEWIRE_H */

/*********************** (C) COPYRIGHT 2024 Milandr ****************************
*
* END OF FILE spacewire.h */


